const players = [
    { name: '科比', num: 24 },
    { name: '詹姆斯', num: 23 },
    { name: '保罗', num: 3 },
    { name: '威少', num: 0 },
    { name: '杜兰特', num: 35 }
]

// forEach
Array.prototype.sx_forEach = function (callback) {
    for (let i = 0; i < this.length; i++) {
        callback(this[i], i, this);
    }
}
players.sx_forEach((item, index, arr) => {
    console.log('forEach: ' + item, index);
})

// map
Array.prototype.sx_map = function (callback) {
    const res = [];
    for (let i = 0; i < this.length; i++) {
        res.push(callback(this[i], i, this));
    }
    return res;
}
console.log(players.sx_map(
    (item, index) => `map: ${item.name}--${item.num}--${index}`)
);

// filter
Array.prototype.sx_filter = function (callback) {
    const res = [];
    for (let i = 0; i < this.length; i++) {
        callback(this[i], i, this) && res.push(this[i]);
    }
    return res;
}
console.log(players.sx_filter(item => item.num >= 23));

// every
Array.prototype.sx_every = function (callback) {
    let flag = true;
    for (let i = 0; i < this.length; i++) {
        flag = callback(this[i], i, this);
        if (!flag) break;
    }
    return flag;
}
console.log('every: ');
console.log(players.sx_every(item => item.num >= 23));
console.log(players.sx_every(item => item.num >= 0));

// some
Array.prototype.sx_some = function (callback) {
    let flag = false;
    for (let i = 0; i < this.length; i++) {
        flag = callback(this[i], i, this);
        if (flag) break;
    }
    return flag;
}
console.log('some: ');
console.log(players.sx_some(item => item.num > 1));
console.log(players.sx_some(item => item.num > 100));

// reduce
Array.prototype.sx_reduce = function (callback, initValue) {
    let start = 0, pre;
    if (initValue) {
        pre = initValue;
    } else {
        pre = this[0].num;
        start = 1;
    }
    for (let i = start; i < this.length; i++) {
        pre = callback(pre, this[i], i, this);
    }
    return pre;
}
const sum = players.sx_reduce((pre, next) => {
    return pre + next.num;
}, 0);
console.log('reduce: ' + sum);

// findIndex
Array.prototype.sx_findIndex = function (callback) {
    for (let i = 0; i < this.length; i++) {
        if (callback(this[i], i, this)) {
            return i;
        }
    }
    return -1;
}
console.log('findIndex: ' + players.sx_findIndex(item => item.num == 0));

// find
Array.prototype.sx_find = function (callback) {
    for (let i = 0; i < this.length; i++) {
        if (callback(this[i], i, this)) {
            return this[i];
        }
    }
    return undefined;
}

console.log('find: ' + players.sx_find(item => item.num == 0));

// fill
Array.prototype.sx_fill = function (value, start = 0, end) {
    end = end || this.length;
    for (let i = start; i < end; i++) {
        this[i] = value;
    }
    return this;
}
console.log(players.sx_fill('Anzia.', 1, 3));

// includes
Array.prototype.sx_includes = function (value, start = 0) {
    if (start < 0) start = this.length + start;
    const isNaN = Number.isNaN(value);
    for (let i = start; i < this.length; i++) {
        if (this[i] === value || Number.isNaN(this[i] === isNaN)) {
            return true;
        }
    }
    return false;
}
console.log('include:');
console.log([1, 2, 3].sx_includes(2));
console.log([1, 2, 3, NaN].sx_includes(NaN));
console.log([1, 2, 3, NaN].sx_includes(1, 1));

// join
Array.prototype.sx_join = function (s = ',') {
    let str = '';
    for (let i = 0; i < this.length; i++) {
        str = i === 0 ? `${str}${this[i]}` : `${str}${s}${this[i]}`;
    }
    return str;
}
console.log('join:');
console.log([1, 2, 3].sx_join());
console.log([1, 2, 3].sx_join('*'));

// flat
Array.prototype.sx_flat = function () {
    let arr = this;
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
    }
    return arr;
}
const testArr = [1, [2, 3, [4, 5]], {a: 1}, [8, 9]];
console.log('flat: ' + testArr.sx_flat());